using System;
using System.Collections.Generic;
using System.Text;
using AgilePlannerDT.Data;
using System.Xml;
using System.Xml.Schema;

namespace AgilePlannerDT.Data.Impl
{
    public class BacklogDataObject : IndexCardWithChildDataObject, Backlog
    {

        #region Constructors

        public BacklogDataObject(Backlog original)
        {
            this.actualEffort = original.ActualEffort;
            this.availableEffort = original.AvailableEffort;
            this.bestCaseEstimate = original.BestCaseEstimate;
            this.description = original.Description;
            this.enddate = original.EndDate;
            this.height = original.Height;
            this.id = original.ID;
            this.locationX = original.LocationX;
            this.locationY = original.LocationY;
            this.mostLikelyEstimate = original.MostlikelyEstimate;
            this.name = original.Name;
            this.parent = original.Parent;
            this.rotationAngle = original.RotationAngle;
            this.startdate = original.StartDate;
            this.status = original.Status;
            this.width = original.Width;
            this.worstCaseEstimate = original.WorstCaseEstimate;

            foreach (StoryCard sc in original.StoryCardChildren)
            {
                AddStoryCard(new StoryCardDataObject(sc));
            }
        }

        public BacklogDataObject()
            : this(0, 1, CardConstants.BACKLOG_DEFAULT_WIDTH, CardConstants.BACKLOG_DEFAULT_HEIGHT, CardConstants.INDEXCARD_DEFAULT_LOCATION_X, CardConstants.INDEXCARD_DEFAULT_LOCATION_Y)
        {
        }

        public BacklogDataObject(double width, double height, double locationX, double locationY)
            : this(0, 1, width, height, locationX, locationY)
        {
        }

        public BacklogDataObject(long id, long parent, double width, double height, double locationX, double locationY)
        {
            this.actualEffort = 0;
            this.availableEffort = 0;
            this.bestCaseEstimate = 0;
            this.description = "Project Backlog";
            this.enddate = new DateTime();
            this.height = height;
            this.id = id;
            this.locationX = locationX;
            this.locationY = locationY;
            this.mostLikelyEstimate = 0;
            this.name = "Project Backlog";
            this.parent = parent;
            this.startdate = new DateTime();
            this.status = CardConstants.STATUS_DEFINED;
            this.width = width;
            this.worstCaseEstimate = 0;
        }

        #endregion

        #region IndexCardWithChild Members

        //not applicable for Backlog
        public new float AvailableEffort
        {
            get { return 0; }
            set { }
        }

        //not applicable for Backlog
        public new float RemainingEffort
        {
            get { return 0; }
        }

        //not applicable for Backlog
        public new DateTime EndDate
        {
            get { return enddate; }
            set { }
        }

        //not applicable for Backlog
        public new DateTime StartDate
        {
            get { return startdate; }
            set { }
        }

        //not applicable for Backlog
        public new bool IsCompleted()
        {
            return false;
        }

        //not applicable for Backlog
        public new bool IsStarted()
        {
            return false;
        }

        #endregion

        #region Backlog Members

        // DOES NOT UPDATE PARENT-CHILD RELATIONS!
        public void Update(Backlog backlog)
        {
            this.id = backlog.ID;
            this.parent = backlog.Parent;
            this.actualEffort = backlog.ActualEffort;
            this.availableEffort = backlog.AvailableEffort;
            this.bestCaseEstimate = backlog.BestCaseEstimate;
            this.description = backlog.Description;
            this.enddate = backlog.EndDate;
            this.height = backlog.Height;
            this.locationX = backlog.LocationX;
            this.locationY = backlog.LocationY;
            this.mostLikelyEstimate = backlog.MostlikelyEstimate;
            this.name = backlog.Name;
            this.rotationAngle = backlog.RotationAngle;
            this.startdate = backlog.StartDate;
            this.status = backlog.Status;
            this.width = backlog.Width;
            this.worstCaseEstimate = backlog.WorstCaseEstimate;
        }

        #endregion

        #region Object Members

        public override string ToString()
        {
            string backlog = "###################################\n" + "#            Backlog              #\n"
                    + "###################################\n\n" + "ID:\t\t" + ID + "\n" + "Name:\t\t" + Name + "\n" + "Parent:\t\t"
                    + Parent + "\n" + "Size:\t\t" + Width + " x " + Height + "\n" + "Location:\t(" + LocationX + " , "
                    + LocationY + ")\n\n";
            return backlog;
        }

        public override bool Equals(object o)
        {
            if (o is BacklogDataObject)
            {
                BacklogDataObject b = (BacklogDataObject)o;

                if (b.StoryCardChildren.Count == StoryCardChildren.Count)
                {
                    bool children = true;

                    for (int i = 0; i < StoryCardChildren.Count; i++)
                    {
                        children = children && b.StoryCardChildren[i].Equals(StoryCardChildren[i]);
                    }

                    return (children && 
                        (b.Height == Height) && 
                        (b.ID == ID) && 
                        (b.Name.Equals(Name)) &&
                        (b.Parent == Parent) && 
                        (b.Width == Width) && 
                        (b.LocationX == LocationX) &&
                        (b.LocationY == LocationY));
                }
            }
            return false;
        }

        public override int GetHashCode()
        {
            return (int)id;
        }

        #endregion

        #region IXmlSerializable Members

        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            Height = double.Parse(reader.GetAttribute("Height"));
            ID = long.Parse(reader.GetAttribute("ID"));
            Name = reader.GetAttribute("Name");
            Parent = long.Parse(reader.GetAttribute("Parent"));
            Width = double.Parse(reader.GetAttribute("Width"));
            LocationX = double.Parse(reader.GetAttribute("XLocation"));
            LocationY = double.Parse(reader.GetAttribute("YLocation"));
            if (!reader.IsEmptyElement)
            {
                reader.Read();
                do
                {
                    StoryCard child = new StoryCardDataObject();
                    child.ReadXml(reader);
                    AddStoryCard(child);
                   
                } while (reader.ReadToNextSibling("StoryCard"));
            }
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteStartElement("Backlog");
            writer.WriteAttributeString("Height", ((int)this.Height).ToString());
            writer.WriteAttributeString("ID", this.ID.ToString());
            writer.WriteAttributeString("Name", this.Name);
            writer.WriteAttributeString("Parent", this.Parent.ToString());
            writer.WriteAttributeString("Width", ((int)this.Width).ToString());
            writer.WriteAttributeString("XLocation", ((int)this.LocationX).ToString());
            writer.WriteAttributeString("YLocation", ((int)this.LocationY).ToString());

            if (StoryCardChildren.Count > 0)
            {
                foreach (StoryCard sc in StoryCardChildren)
                {
                    sc.WriteXml(writer);
                }
            }

            writer.WriteEndElement();
        }

        #endregion

        #region ICloneable Members

        public override object Clone()
        {
            return new BacklogDataObject(this);
        }

        #endregion
    }
}